import archiver from 'archiver';
import dayjs from 'dayjs';
import fs from 'node:fs';
import { URL, fileURLToPath } from 'node:url';
import { Client as Ssh } from 'ssh2';
import sftp from 'ssh2-sftp-client';

const devCertPath = fileURLToPath(
  new URL('./cert/192.168.100.140.pem', import.meta.url),
);
const testCertPath = fileURLToPath(
  new URL('./cert/test_id_ed25519.pem', import.meta.url),
);

const devConfig = {
  host: '192.168.100.140',
  port: 22,
  username: 'root',
  privateKey: fs.readFileSync(devCertPath),
};

const testConfig = {
  host: '192.168.100.100',
  port: 22,
  username: 'root',
  privateKey: fs.readFileSync(testCertPath),
};

const sourcePath = fileURLToPath(new URL('../dist', import.meta.url));
const outputPath = fileURLToPath(new URL('../dist.zip', import.meta.url));

const zip = () => {
  return new Promise((resolve, reject) => {
    const output = fs.createWriteStream(outputPath);
    const archive = archiver('zip', {
      zlib: { level: 9 }, // 设置压缩级别
    });
    output.on('close', () => {
      console.log('文件已压缩');
      resolve();
    });

    archive.on('error', (err) => {
      console.error(err);
      reject(err);
    });
    archive.pipe(output);
    archive.directory(sourcePath, false);
    archive.finalize();
  });
};

const uploadZip = async (config, path = 'ebs2.dev') => {
  const s = new sftp();
  try {
    await s.connect(config);
    console.log('连接成功---开始上传 dist 包');
    await s.put(outputPath, `/www/wwwroot/${path}/dist.zip`);
    console.log('文件上传成功');
  } catch (error) {
    console.log(error);
    console.log('文件上传失败');
    throw new Error();
  }
};

const unzip = (config, path = 'ebs2.dev') => {
  const conn = new Ssh();
  const backDist = () => {
    return new Promise((resolve, reject) => {
      conn.exec(
        `mv /www/wwwroot/ims.${path}.boeyo.com/dist /www/wwwroot/${path}/dist_${dayjs().format('YYYY_MM_DD_HH_mm_ss')}`,
        (err, stream) => {
          if (err) {
            console.log(err);
            reject();
            return;
          }
          stream
            .on('close', (code, signal) => {
              console.log(
                'Stream :: close :: code: ' + code + ', signal: ' + signal,
              );
              console.log('dist备份成功');
              resolve();
            })
            .on('data', (data) => {
              console.log('STDOUT: ' + data);
            })
            .stderr.on('data', (data) => {
              console.log('STDERR: ' + data);
            });
        },
      );
    });
  };
  const rmOldDist = () => {
    return new Promise((resolve, reject) => {
      conn.exec(`rm -rf /www/wwwroot/${path}/dist`, (err, stream) => {
        if (err) {
          console.log(err);
          reject();
          return;
        }
        stream
          .on('close', (code, signal) => {
            console.log(
              'Stream :: close :: code: ' + code + ', signal: ' + signal,
            );
            console.log('dist 删除成功');
            resolve();
          })
          .on('data', (data) => {
            console.log('STDOUT: ' + data);
          })
          .stderr.on('data', (data) => {
            console.log('STDERR: ' + data);
          });
      });
    });
  };

  const mkdirDist = () => {
    return new Promise((resolve, reject) => {
      conn.exec(`mkdir -p /www/wwwroot/${path}/dist`, (err, stream) => {
        if (err) {
          console.log(err);
          reject();
          return;
        }
        stream
          .on('close', (code, signal) => {
            console.log(
              'Stream :: close :: code: ' + code + ', signal: ' + signal,
            );
            console.log('mkdir dist');
            resolve();
          })
          .on('data', (data) => {
            console.log('STDOUT: ' + data);
          })
          .stderr.on('data', (data) => {
            console.log('STDERR: ' + data);
          });
      });
    });
  };

  const _unzip = () => {
    return new Promise((resolve, reject) => {
      conn.exec(
        `unzip -d /www/wwwroot/${path}/dist/ /www/wwwroot/${path}/dist.zip`,
        (err, stream) => {
          if (err) {
            console.log(err);
            reject();
            return;
          }
          stream
            .on('close', (code, signal) => {
              console.log(
                'Stream :: close :: code: ' + code + ', signal: ' + signal,
              );
              console.log('解压成功');
              resolve();
            })
            .on('data', (data) => {
              console.log('STDOUT: ' + data);
            })
            .stderr.on('data', (data) => {
              console.log('STDERR: ' + data);
            });
        },
      );
    });
  };

  return new Promise((resolve, reject) => {
    conn
      .on('ready', async () => {
        // console.log('开始备份 dist')
        // await backDist();
        await rmOldDist();
        await mkdirDist();
        console.log('开始解压 dist.zip');
        await _unzip();
        resolve();
      })
      .connect(config);
  });
};

const deploy = async () => {
  // 压缩 dist
  await zip();
  // 上传
  await uploadZip(devConfig, 'ims.dev');
  // await uploadZip(testConfig, 'test');
  // 服务器中解压
  await unzip(devConfig, 'ims.dev');
  // await unzip(testConfig, 'test');

  fs.unlinkSync(outputPath);
  process.exit();
};

deploy();
